home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
wmv12s.zip
/
NORMAL.C
< prev
next >
Wrap
Text File
|
1993-01-04
|
10KB
|
430 lines
/* The normal routine "normalizes" a given path name to this form:
** drv:\id\id\id...\id
** so that two identical directory/file will yield the same normalized
** path regardless of how the user typed it in
** E.g.
** a:\x\y
** and a:\X\Y\.
** both yield A:\X\Y
**
** In addition, the later one would also set the flag "dir" indicating
** that the user specified it as an directory.
**
** Written by Peter Wu @ Faculty Support Center @ Univ. of Wisconsin
** 7/14/86
*/
#define LINT_ARGS
#define T_ID1 1 /* id without period */
#define T_ID2 2 /* id with period */
#define T_DOT 3 /* '.' */
#define T_DD 4
#define T_BS 5
#define T_COL 6
#define T_NUL 0
#define PLEN 200
#include "dta.h"
#include <dos.h>
#include <string.h>
#include <conio.h>
char *insert();
index(str,c) /* first occurence of c in str */
char *str, c;
{
char *i, d;
i = str;
d = *i;
while (d != '\0') {
if (d == c) {
return i - str;
}
i++;
d = *i;
}
return -1;
}
char lastc(str) /* return last character of the string */
register char *str;
{
if (*str == '\0') {
return '\0';
}
do {
str++;
} while (*str != '\0');
return *(str-1);
}
normal(path) /* normalize a path */
char *path;
{
char work1[PLEN], work2[PLEN], token[13], token2[13], *ptr;
int i, drv, marker, t, ftype, t2;
/* first make the path a complete path (include drive, and root) */
i = index(path, ':'); /* search for ':' */
if (i < 0) { /* no drive specification */
if (*path == '\\') { /* start from root */
work1[0] = '@' + drive(); /* default disk */
work1[1] = ':';
work1[2] = '\0';
strcat(work1, path); /* now we have full path */
} else { /* no drive and no root */
current(0,work1); /* get current drive and path */
strcat(work1, path); /* now we have full path */
}
} else { /* has drive specification */
if (path[i+1] != '\\') { /* but no root, so insert current path */
drv = toupper(path[i-1]) - '@'; /* get drive number */
current(drv,work1); /* put down drive and path */
strcat(work1, path+i+1); /* now we have full path */
} else { /* nothing to change */
strcpy(work1,path);
}
}
#ifdef debug
printf("full path is %s\n", work1);
#endif
/* now we have full path in work, but we need to normalize it to get rid
** of .. and .
*/
marker = -2;
work2[PLEN-1] = '\0'; /* this is where we accumulate result backwards */
ptr = work2 + PLEN - 1; /* point to first char */
ftype = -1; /* -1=init, 0=unknown, A_DIR=dir */
do {
t = scan(work1,&marker,token);
#ifdef debug
printf("ptr is %s so far, and t=%d\n", ptr, t);
#endif
switch (t) {
case T_ID1:
case T_ID2:
ptr = insert(token, ptr);
if (ftype == -1) {
ftype = 0; /* this could be a file or a directory */
}
break;
#ifdef ha
case T_ID2:
if (ftype == -1) {
ptr = insert(token, ptr);
ftype = 0; /* this could be file or a directory */
} else {
putn("invalid sub-directory name \"", token, "\"\n\015",0);
exit(1);
}
break;
#endif
case T_DD:
t2 = scan(work1,&marker,token); /* see what's in front of .. */
if (t2 != T_BS) {
cputs("incorrect use of \"..\" in path name\n\015");
exit(1);
}
/* now delete \id\.. */
t2 = scan(work1,&marker,token); /* read the id (hopefully) */
if (t2 != T_ID1) {
if (t2 == T_COL) { /* A:\.. is not permitted */
cputs("sorry, but root directory has no parent\n\015");
exit(1);
} else { /* what could t2 be? */
cputs("missing directory name in front of \"\\..\"\n\015");
exit(1);
}
}
t2 = scan(work1,&marker,token2); /* read the '\' */
if (t2 != T_BS) { /* can this ever happen? */
putn("missing \"\\\" before \"", token, "\" in path\n\015",0);
exit(1);
}
/* a:\id\.. should yield a:\ not a:
** a:\id1\..\id2 should yield a:\id2
** this is taken care of somewhere else
*/
/* ok, \id\.. deleted */
if (ftype == -1) {
ftype = A_DIR; /* this has to be a directory */
}
break;
case T_DOT:
t2 = scan(work1,&marker,token); /* read the '\' */
if (t2 != T_BS) { /* is this error possible? */
cputs("missing \"\\\" in front of \".\"\n\015");
exit(1);
}
if (ftype == -1) {
ftype = A_DIR; /* this has to be a directory */
}
/* special case is "a:\." we want this to turn into "A:\" and
** not "A:"
*/
break;
case T_BS:
ptr = insert("\\", ptr);
break;
case T_COL:
ptr = insert(":", ptr);
break;
}
} while (t != T_NUL);
if (lastc(ptr) == ':') { /* special case like a: */
strcat(ptr,"\\");
}
strcpy(path,ptr); /* copy normalized path back */
return ftype;
}
char *insert(str1,str2) /* insert str1 in front of str2 */
char *str1, *str2;
{
int i;
i = strlen(str1);
return strncpy(str2 - i, str1, i);
}
scan(path,marker,tstr) /* return tokens backwards */
char *path, *tstr;
int *marker;
{
char c, d;
if (*marker == -2) { /* signal new scan */
*marker = strlen(path) - 1;
}
if (*marker == -1) {
return T_NUL; /* end of string */
}
c = path[*marker];
if ( ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) ) {
return collect_id(tstr, path, marker);
}
switch (c) {
case '.':
if (*marker == 0) {
*marker = -1;
return T_DOT;
} else {
d = path[*marker - 1];
if (d == '.') {
*marker -= 2;
return T_DD;
} else {
if ((d == '\\') || (d == ':')) {
(*marker)--;
return T_DOT;
} else { /* must be an id with trailing dot */
return collect_id(tstr, path, marker);
}
}
}
cputs("how do I get here?\n\015");
error("scan", 0);
case '\\':
(*marker)--;
return T_BS;
case ':':
(*marker)--;
return T_COL;
default:
return collect_id(tstr, path, marker); /* non-alpha ID */
}
}
check_fn(fn) /* look for invalid characters in file name */
char *fn;
{
char c, *s;
s = fn;
while((c= *s) != '\0') {
if ((c < 32) || (index("\"[]|<>+=;,/",c) > -1)) {
cputs("invalid character '"); putch(c);
putn("' in file/sub-directory name \"", fn, "\"", 0);
exit(1);
}
s++;
}
}
collect_id(tstr, path, marker)
char *tstr, *path;
int *marker;
{
char c, id[13];
int flag, i;
id[13] = '\0';
i = 12;
flag = T_ID1; /* no period in file name */
do {
c = path[*marker];
if (c == '.') { /* indicate there's period in the file name */
flag = T_ID2;
} else {
c = toupper(c);
if ((c == '\\') || (c == ':')) { /* end of file name */
strncpy(tstr, id+i+1, 13);
check_fn(tstr);
return flag;
}
}
id[i] = c;
(*marker)--;
if (*marker < 0) {
strncpy(tstr, id+i, 13);
check_fn(tstr);
return flag;
}
i--;
} while (i >= 0);
putn("file/sub-directory name \"...", id, "\" too long\n\015", 0);
exit(1);
}
drive() /* returns current drive number 1=A 2=B */
{
return (char) bdos(0x19, 0, 0) + 1;
}
current(drv,cpath) /* returns current path "drv:\id\..\id on drv */
char *cpath;
int drv;
{
union REGS inregs, outregs;
char tmp[64];
inregs.h.ah = 0x47; /* get current path */
inregs.x.si = (int) tmp;
inregs.h.dl = drv; /* drive number 0=default, 1=A, 2=B */
intdos(&inregs, &outregs);
if (drv == 0) {
drv = drive();
}
if (outregs.x.cflag) {
cputs("cannot find current path on drive "); putch('@'+drv);
cputs(":\n\015");
error("current", 0);
} else {
cpath[0] = '@' + drv;
cpath[1] = ':';
cpath[2] = '\\';
cpath[3] = '\0';
if (*tmp != '\0') { /* if not root directory, then append path */
strcat(cpath,tmp);
strcat(cpath,"\\");
}
}
}
catpath(path, name) /* concatenate name to path, adding \ when neccessary */
char *path, *name;
{
if (path[strlen(path)-1] != '\\') {
strcat(path, "\\");
}
strcat(path, name);
}
chopath(path) /* chop off the last portion of a path */
char *path;
{
char *tmp;
tmp = strrchr(path, '\\');
if (tmp == (char *)0) {
putn("can't find '\\' in ", path, "\n\015");
error("chopath", 0);
}
if (*(tmp-1) == ':') { /* special case for root */
*(tmp+1) = '\0';
} else {
*tmp = '\0';
}
}
#define A_INT 0x80 /* interactive flag */
/* extract the file-type specifier from the given path.
** E.g. x/f becomes x with file type,
** animal\dog/d becomes animal\dog with sub-directory type,
** *./f becomes *. with file type
** *.* becomes *.* with no type
** *./i becomes interactive (i.e. prompts for y/n for each file)
*/
extype(path)
char *path;
{
char *s;
int type;
s = strrchr(path,'/'); /* find last '/' */
if (s == (char *) 0) { /* no type specified */
return 0;
}
type = 0;
*s = '\0';
for (++s; *s != '\0'; s++) { /* start scanning after the '/' */
switch (*s) {
case 'f':
case 'F':
type |= A_FIL;
break;
case 'd':
case 'D':
type |= A_DIR;
break;
case 'h':
case 'H':
type |= A_HID; /* search for hidden files */
break;
case 'i':
case 'I':
type |= A_INT; /* requires user's confirmation for each file */
break;
default:
cputs("unrecognized file attribute '"); putch(*s);
putn("' in path \"", path, "\"\n\015",
"valid attributes are f, d, h, i (for file, directory, hidden, interac)\n\015",
0);
exit(1); /* maybe the user doesn't know what he/she's doing */
}
}
return type;
}